package com.pig4cloud.pig.ads.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pig.ads.exception.CommentException;
import com.pig4cloud.pig.ads.pig.mapper.AdCommentMapper;
import com.pig4cloud.pig.ads.pig.mapper.AdTermBannedMapper;
import com.pig4cloud.pig.ads.pig.mapper.AdvertiserMapper;
import com.pig4cloud.pig.ads.pig.mapper.TtAccesstokenMapper;
import com.pig4cloud.pig.ads.service.AdAccountService;
import com.pig4cloud.pig.ads.service.AdTermBannedService;
import com.pig4cloud.pig.ads.service.TtCommentApiService;
import com.pig4cloud.pig.api.dto.AdTermBannedDto;
import com.pig4cloud.pig.api.entity.*;
import com.pig4cloud.pig.api.vo.AdAccountVo;
import com.pig4cloud.pig.api.vo.AdTermBannedVo;
import com.pig4cloud.pig.api.vo.TtResultVo;
import com.pig4cloud.pig.common.core.constant.CommonConstants;
import com.pig4cloud.pig.common.core.constant.enums.PlatformTypeEnum;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class AdTermBannedServiceImpl extends ServiceImpl<AdTermBannedMapper, AdTermBannedEntity> implements AdTermBannedService {

	private static final ZoneOffset DONGBA_DISTRICT_OFFSET = ZoneOffset.ofHours(8);

	private final AdTermBannedMapper adTermBannedMapper;

	private final TtCommentApiService ttCommentApiService;

	private final AdvertiserMapper advertiserMapper;

	private final TtAccesstokenMapper ttAccesstokenMapper;

	private final AdCommentMapper adCommentMapper;

	//	private final AdvService advService;
	private final AdAccountService adAccountService;

	/**
	 * 获取屏蔽词分页列表
	 *
	 * @param req
	 * @return
	 */
	@Transactional(readOnly = true)
	@Override
	public Page<AdTermBannedEntity> getTermsPage(AdTermBannedVo req) {
		LambdaQueryWrapper<AdTermBannedEntity> queryWrapper = Wrappers.<AdTermBannedEntity>lambdaQuery().eq(AdTermBannedEntity::getIsDeleted, 0);

		// 获取当前用户拥有的广告账户
//		Set<String> advertiserIds = advService.getAccountList(Integer.parseInt(PlatformTypeEnum.TT.getValue()), null).stream().map(AdAccount::getAdvertiserId).collect(Collectors.toSet());
		Set<String> advertiserIds = adAccountService.getAccountsByAuthorize(new AdAccountVo().setMediaCode(PlatformTypeEnum.TT.getValue())).stream().map(AdAccount::getAdvertiserId).collect(Collectors.toSet());
		if (CollectionUtil.isEmpty(advertiserIds)) {
			// 当前帐户下没有广告账户
			return new Page<AdTermBannedEntity>().setTotal(0).setCurrent(req.getCurrent()).setSize(req.getSize()).setRecords(Collections.emptyList());
		}
		queryWrapper.in(!advertiserIds.isEmpty(), AdTermBannedEntity::getAdvertiserId, advertiserIds).eq(AdTermBannedEntity::getIsDeleted, 0)
				.like(StringUtils.isNotEmpty(req.getAdvertiserName()), AdTermBannedEntity::getAdvertiserName, req.getAdvertiserName())
				.like(StringUtils.isNotEmpty(req.getTerms()), AdTermBannedEntity::getTerms, req.getTerms())
				.orderByDesc(AdTermBannedEntity::getCreateDate);
		return this.getBaseMapper().selectPage(req, queryWrapper);
	}

	/**
	 * 添加屏蔽词
	 *
	 * @param req
	 */
	@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ, rollbackFor = Exception.class)
	@Override
	public void addTerms(AdTermBannedVo req) {
		List<String> termsList = req.getTermsList();
		if (req.getTermsList().stream().anyMatch(e -> null == e || e.length() == 0 || e.length() > 20)) {
			throw new CommentException(CommonConstants.FAIL, "屏蔽词不能为空并且长度不允许超过20");
		}
		if (termsList.stream().distinct().count() != termsList.size()) {
			throw new CommentException(CommonConstants.FAIL, "提交的多个屏蔽词有重复的内容");
		}

		// 校验屏蔽词是否存在
		Set<String> existsSet = baseMapper.selectList(Wrappers.<AdTermBannedEntity>lambdaQuery().select(AdTermBannedEntity::getTerms).eq(AdTermBannedEntity::getIsDeleted, 0).eq(AdTermBannedEntity::getAdvertiserId, req.getAdvertiserId())
				.in(AdTermBannedEntity::getTerms, termsList)).stream().map(AdTermBannedEntity::getTerms).collect(Collectors.toSet());
		if (!existsSet.isEmpty()) {
			throw new CommentException(CommonConstants.FAIL, "屏蔽词“" + String.join(",", existsSet) + "”已存在");
		}

		// 保存屏蔽词数据
		baseMapper.batchInsert(termsList.stream().map(text -> new AdTermBannedEntity().setTerms(text).setAdvertiserId(req.getAdvertiserId()).setAdvertiserName(req.getAdvertiserName()).setCreateDate(new Date()).setUpdateDate(new Date())).collect(Collectors.toList()));

		// 更新当前广告账户下，一个月内创建的评论是否包含屏蔽词
		updateCommentContainTermsBanned(req.getAdvertiserId());

		// 查询token
		String accessToken = findAccessToken(req.getAdvertiserId());
		// 调用接口添加
		TtResultVo result = ttCommentApiService.termsBannedAdd(Long.parseLong(req.getAdvertiserId()), accessToken, termsList);
		if (!result.getSuccess()) { // 调用失败
			throw new CommentException(CommonConstants.FAIL, result.getMessage());
		}
	}

	/**
	 * 修改屏蔽词
	 *
	 * @param req
	 */
	@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ, rollbackFor = Exception.class)
	@Override
	public void editTerms(AdTermBannedVo req) {
		AdTermBannedEntity terms = this.getOne(Wrappers.<AdTermBannedEntity>lambdaQuery().eq(AdTermBannedEntity::getId, req.getId()).eq(AdTermBannedEntity::getIsDeleted, 0));
		if (null == terms) {
			return;
		}
		if (StringUtils.isEmpty(req.getTerms()) || req.getTerms().length() > 20) {
			throw new CommentException(CommonConstants.FAIL, "屏蔽词不能为空并且长度不允许超过20");
		}
		if (req.getTerms().equals(terms.getTerms())) {
			return;
		}
		// 校验当前广告账户下是否存在要更新的屏蔽词
		if (this.count(Wrappers.<AdTermBannedEntity>lambdaQuery().eq(AdTermBannedEntity::getIsDeleted, 0).eq(AdTermBannedEntity::getAdvertiserId, terms.getAdvertiserId()).eq(AdTermBannedEntity::getTerms, req.getTerms())) > 0) {
			throw new CommentException(CommonConstants.FAIL, "要更新的屏蔽词在当前账号已存在");
		}
		this.updateById(new AdTermBannedEntity().setId(req.getId()).setTerms(req.getTerms()).setUpdateDate(new Date()));

		// 更新当前广告账户下，一个月内创建的评论是否包含屏蔽词
		updateCommentContainTermsBanned(terms.getAdvertiserId());

		//查询token
		String accessToken = findAccessToken(terms.getAdvertiserId());
		//调用接口
		TtResultVo result = ttCommentApiService.termsBannedUpdate(Long.parseLong(terms.getAdvertiserId()), accessToken, terms.getTerms(), req.getTerms());
		if (!result.getSuccess()) { // 调用失败
			throw new CommentException(CommonConstants.FAIL, result.getMessage());
		}
	}

	/**
	 * 删除屏蔽词
	 *
	 * @param id
	 */
	@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ, rollbackFor = Exception.class)
	@Override
	public void deleteTerms(Long id) {
		AdTermBannedEntity terms = this.getOne(Wrappers.<AdTermBannedEntity>lambdaQuery().eq(AdTermBannedEntity::getId, id).eq(AdTermBannedEntity::getIsDeleted, 0));
		if (null == terms) {
			return;
		}
		this.updateById(new AdTermBannedEntity().setId(id).setIsDeleted(1).setUpdateDate(new Date()));

		// 更新当前广告账户下，一个月内创建的评论是否包含屏蔽词
		updateCommentContainTermsBanned(terms.getAdvertiserId());

		// 查询token
		String accessToken = findAccessToken(terms.getAdvertiserId());
		// 调用接口
		TtResultVo result = ttCommentApiService.termsBannedDelete(Long.parseLong(terms.getAdvertiserId()), accessToken, Collections.singletonList(terms.getTerms()));
		if (!result.getSuccess()) { // 调用失败
			throw new CommentException(CommonConstants.FAIL, result.getMessage());
		}

	}

	private void updateCommentContainTermsBanned(String advertiserId) {
		// 时间范围为最近一个月
		LocalDateTime now = LocalDateTime.now();
		Date startDay = new Date(now.minusMonths(1).toInstant(DONGBA_DISTRICT_OFFSET).toEpochMilli());
		Date endDay = new Date(now.toInstant(DONGBA_DISTRICT_OFFSET).toEpochMilli());

		// 获取当广告前帐户下所有屏蔽词
		List<AdCommentEntity> commentList = adCommentMapper.selectList(Wrappers.<AdCommentEntity>query().eq("`rank`", 1).lambda().select(AdCommentEntity::getId, AdCommentEntity::getText, AdCommentEntity::getAdvertiserId)
				.eq(AdCommentEntity::getAdvertiserId, advertiserId).between(AdCommentEntity::getCreateDate, startDay, endDay).eq(AdCommentEntity::getIsDelete, 0));

		if (!commentList.isEmpty()) {

			// 获取屏蔽词
			Set<String> termsSet = adTermBannedMapper.selectList(Wrappers.<AdTermBannedEntity>lambdaQuery().select(AdTermBannedEntity::getTerms).eq(AdTermBannedEntity::getAdvertiserId, advertiserId).eq(AdTermBannedEntity::getIsDeleted, 0)).stream().map(AdTermBannedEntity::getTerms).collect(Collectors.toSet());

			// 更新包含屏蔽词的评论
			for (AdCommentEntity comment : commentList) {
				// 判断是否包含屏蔽词
				String termsBanned = termsSet.stream().filter(termsValue -> comment.getText().contains(termsValue)).collect(Collectors.joining(","));
				adCommentMapper.updateById(new AdCommentEntity().setId(comment.getId()).setIsTermsBanned(termsBanned.length() > 0 ? 1 : 0).setTermsBannedList(termsBanned).setUpdateDate(new Date()));
			}

		}
	}


	@Deprecated
	@Override
	public IPage<AdTermBannedVo> selectPageList(AdTermBannedDto dto) {
		Integer userId = SecurityUtils.getUser().getId();
		//获取当前账号下 广告账户列表
//		List<String> advertiserIds = advService.getOwnerAdv(userId, PlatformTypeEnum.TT.getValue());
		List<String> advertiserIds = adAccountService.getAccountsByAuthorize(new AdAccountVo().setMediaCode(PlatformTypeEnum.TT.getValue())).stream().map(AdAccount::getAdvertiserId).collect(Collectors.toList());
		if (CollectionUtils.isEmpty(advertiserIds)) {
			return new Page();
		}
		dto.setAdvertiserIds(advertiserIds);
		return adTermBannedMapper.selectPageList(dto);
	}

	@Deprecated
	@Override
	@Transactional
	public R addTerms(AdTermBannedDto dto) {
		String advertiser_id = dto.getAdvertiser_id();
		List<String> termsList = dto.getTerms_list();
		List<AdTermBannedEntity> entityList = new ArrayList<AdTermBannedEntity>();
		List<AdTermBannedEntity> adTermBannedEntities = null;
		for (String term : termsList) {
			if (term.length() > 100) {
				throw new CommentException(CommonConstants.FAIL, "每个屏蔽词长度不允许超过100个");
			}
			adTermBannedEntities = baseMapper.selectList(Wrappers.<AdTermBannedEntity>query().lambda().eq(AdTermBannedEntity::getAdvertiserId, dto.getAdvertiser_id()).eq(AdTermBannedEntity::getTerms, term).eq(AdTermBannedEntity::getIsDeleted, CommonConstants.STATUS_NORMAL));
			if (CollectionUtils.isNotEmpty(adTermBannedEntities)) {
				continue;
			}
			AdTermBannedEntity entity = new AdTermBannedEntity();
			entity.setTerms(term);
			entity.setAdvertiserId(advertiser_id);
			entity.setAdvertiserName(dto.getAdvertiser_name());
			entityList.add(entity);
		}
		//批量插入数据库
		if (entityList.size() > 0) {
			Integer r = adTermBannedMapper.batchInsert(entityList);
			if (r <= 0) {
				throw new CommentException(CommonConstants.FAIL, "新增保存失败");
			}
		}
		//查询token
		String accessToken = findAccessToken(advertiser_id);
		//调用接口添加
		TtResultVo result = ttCommentApiService.termsBannedAdd(Long.parseLong(advertiser_id), accessToken, termsList);
		if (!result.getSuccess()) {//调用失败
			throw new CommentException(CommonConstants.FAIL, result.getMessage());
		}
		return R.ok("", "操作成功");
	}

	@Deprecated
	@Override
	@Transactional
	public R deleteTerms(AdTermBannedDto dto) {
		AdTermBannedEntity termEntity = adTermBannedMapper.selectById(dto.getId());
		if (null == termEntity) {
			throw new CommentException(CommonConstants.FAIL, "屏蔽词不存在");
		}

		String advertiser_id = termEntity.getAdvertiserId();
		Integer r = adTermBannedMapper.deleteById(dto.getId());
		if (r <= 0) {
			throw new CommentException(CommonConstants.FAIL, "数据库删除失败");
		}
		//查询token
		String accessToken = findAccessToken(advertiser_id);
		//调用接口
		List<String> termsList = new ArrayList<>();
		termsList.add(termEntity.getTerms());
		TtResultVo result = ttCommentApiService.termsBannedDelete(Long.parseLong(advertiser_id), accessToken, termsList);
		if (!result.getSuccess()) {//调用失败
			throw new CommentException(CommonConstants.FAIL, result.getMessage());
		}
		return R.ok("", "操作成功");
	}

	@Deprecated
	@Override
	@Transactional
	public R updateTerms(AdTermBannedDto dto) {
		AdTermBannedEntity entity = adTermBannedMapper.selectById(dto.getId());
		if (null == entity) {
			return R.failed("未查找到屏蔽词");
		}
		String origin_terms = entity.getTerms();
		String terms = dto.getTerms();

		if (null == terms) {
			throw new CommentException(CommonConstants.FAIL, "屏蔽词不允许为空");
		} else {
			if (terms.length() > 100) {
				throw new CommentException(CommonConstants.FAIL, "每个屏蔽词长度不允许超过100个");
			}
			List<AdTermBannedEntity> adTermBannedEntities = baseMapper.selectList(Wrappers.<AdTermBannedEntity>query().lambda().eq(AdTermBannedEntity::getAdvertiserId, entity.getAdvertiserId()).eq(AdTermBannedEntity::getTerms, terms).eq(AdTermBannedEntity::getIsDeleted, CommonConstants.STATUS_NORMAL));
			adTermBannedEntities = adTermBannedEntities.stream().filter(t -> !t.getId().equals(dto.getId())).collect(Collectors.toList());
			if (CollectionUtils.isNotEmpty(adTermBannedEntities)) {
				throw new CommentException(CommonConstants.FAIL, "当前屏蔽词在当前账号已存在");
			}
		}

		String advertiser_id = entity.getAdvertiserId();
		entity.setTerms(dto.getTerms());
		Integer r = adTermBannedMapper.updateById(entity);
		if (r <= 0) {
			return R.failed("数据库更新失败");
		}
		//查询token
		String accessToken = findAccessToken(advertiser_id);
		//调用接口
		TtResultVo result = ttCommentApiService.termsBannedUpdate(Long.parseLong(advertiser_id), accessToken, origin_terms, dto.getTerms());
		if (!result.getSuccess()) {//调用失败
			throw new CommentException(CommonConstants.FAIL, result.getMessage());
		}
		return R.ok("", "操作成功");
	}

	//查询token
	private String findAccessToken(String advertiser_id) {
		Advertising advertising = advertiserMapper.selectById(advertiser_id);
		if (null == advertising) {
			throw new CommentException(CommonConstants.FAIL, "未找到对应广告账户");
		}
		TtAccesstoken token = ttAccesstokenMapper.selectById(advertising.getHousekeeper());
		if (null == token) {
			throw new CommentException(CommonConstants.FAIL, "未找到对应AccessToken");
		}
		return token.getAccessToken();
	}
}
